/*

Program : Gauss Seidel iteration
*/
#include"matrix.h"




class SeidelIteretion : public Matrix
{
      public: 
    double B[100],prevVal[100],currVal[100];
    
   SeidelIteretion();
   
   int isDiagonalDominant(); 
   
   int tolerence();
   void jacobi();
   void storeVal();
   
   void swapBRow(int ,int);
   void initialIteretion();
   void iteretion(int);   

   void printAll();
   
   void useDefaultB();
};



int SeidelIteretion::tolerence()
{
 double tol;
 double prev,curr; 
    for(int i=0;i<row;i++)
    {
       if(prevVal[i]<0)
          prev=(-1)*prevVal[i];
       else
         prev=(1)*prevVal[i];	        
	 
      if(currVal[i]<0)
          curr=(-1)*currVal[i];
       else
         curr=(1)*currVal[i];	        
	 
	 
    
        tol=prev-curr;
       
           if(tol>0.0000000001)
	   
	   return 0;
    }                  
 
return 1;
}


void SeidelIteretion::printAll()
{
  cout<<endl;
  
    cout.precision(10);
     for(int i=0;i<row;i++)     
     {
       cout<<prevVal[i]<<"   "<<currVal[i]<<endl;   
     }
     

}


void SeidelIteretion::swapBRow(int currRow,int nextRow)
 {
 
  double temp;
  
          temp=(double)B[currRow];
	  B[currRow]=(double)B[nextRow];
	  B[nextRow]=(double)temp;
	
} 
	
void SeidelIteretion::storeVal()
{
  
  	  for(int i=0;i<row;i++)      
	  {
	    prevVal[i]=(double)currVal[i];
	  
	  }
}

void SeidelIteretion::useDefaultB()
{
         B[0]=6;
	 B[1]=5;
	 B[2]=-1;
	 
   for(int i=0;i<row;i++) 	 
   {
       prevVal[i]=0;
       currVal[i]=0;
    
   }
   cout<<"Inside Use default"<<endl;
   printAll();
}

void SeidelIteretion::jacobi()
   {
       useDefault(); 
       useDefaultB();
       isDiagonalDominant(); 
       printMatrix();
       initialIteretion();
       int cnt=0;
        while(1)
	{
	   
	  for(int i=0;i<row;i++)      
	    iteretion(i);
	   
	   
	   if(tolerence()==1)
	     break;
	  cnt++; 
	  storeVal();
         }
           
    printAll();   
    
    cout<<"\nTotal Iteration's : "<<cnt;
    
   
   }


void SeidelIteretion::initialIteretion()
{
     
     for(int i=0;i<row;i++)   
     {
         prevVal[i]=((double)B[i])/((double)matrix[i][i]);    
	 
//cout<<" prevVal= "<<prevVal[row]<<"  B[]="<<B[row]<<"  matrix[][]"<<matrix[row][row]<<"For Row="<<row<<endl;
     }
     
   cout<<"Inside initial"<<endl;  
    printAll();
}      
   

void SeidelIteretion::iteretion(int row)   
{
  double add;
  add=0;   
     for(int j=0;j<column;j++)
     {
         if(j!=row)
	  add=add+(double)(matrix[row][j]*prevVal[j]);
     }     
  
     
  add=(double)B[row]-add;
        
  currVal[row]=add/((double) matrix[row][row]);

}



SeidelIteretion::SeidelIteretion()
{
   //initialize all zero
   
   

}


int SeidelIteretion::isDiagonalDominant()
{
    double add,temp;
    
	for(int i=0;i<row;i++)
	{
	  add=0;
	  for(int j=0;j<column;j++)
	  {
            if(i!=j)
	    { 
	      if(matrix[i][j]<0)
	       temp=(-1)*matrix[i][j];
	      else
	       temp=matrix[i][j];  
	    
	    add=add+temp; 
	    }
	    
	  }
	  
	    if(matrix[i][i]<0)
	       temp=(-1)*matrix[i][i];
	      else
	       temp=matrix[i][i];  
	  
	  
	  if(add>temp)
	  {
	    if(i==row)
	    {
	      swapRow(i,i-1);
	      swapBRow(i,i-1);
	     } 
	    else
	    {
	     swapRow(i,i+1);
	     swapBRow(i,i+1);
	     
	     }
	  }  
	  
	}     
	
   return 1;

}





